package part1.miniTomcat;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author 大忽悠
 * @create 2022/9/1 9:28
 */
@Slf4j
public class Server {
    /**
     * 当前WEB项目的根目录
     */
    public static final String WEB_ROOT=System.getProperty("user.dir")+ File.separator+"web-app";

    /**
     * 停止服务器的命令
     */
    private static final String SHUTDOWN_COMMAND="/shutdown";

    /**
     * 默认启动端口
     */
    private static final Integer DEFAULT_PORT=8080;

    /**
     *  停止信号的是否发出
     */
    private boolean shutdown=false;

    /**
     * 服务器监听端口号
     */
    private Integer port=DEFAULT_PORT;

    /**
     * 服务端等待队列最大连接数
     */
    private Integer backLog=1;

    public void start(){
      ServerSocket serverSocket=null;

        try {
            serverSocket=new ServerSocket(port,backLog, InetAddress.getByName("127.0.0.1"));
            log.info("miniTomcat在{}端口启动,客户端最大连接数被设置为{}",port,backLog);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        //轮询监听客户端请求
        while(!shutdown){
            Socket client = null;
            try {
              client=serverSocket.accept();
              log.info("客户端[{}]请求正在被处理...",client.getRemoteSocketAddress());
              OutputStream out = client.getOutputStream();
              InputStream in = client.getInputStream();

              log.info("请求解析中....");
              Request request = new Request(in);
              request.parse();

              log.info("发送响应中....");
              Response response = new Response(out);
              response.setRequest(request);
              response.sendStaticResource();

              //本次客户端连接处理结束
              client.close();

              //检查是否是关闭服务器请求
              shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void setShutdown(boolean shutdown) {
        this.shutdown = shutdown;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    /**
     * <p>backlog:</p>
     * <p>服务端socket处理客户端socket连接是需要一定时间的。 </p>
     * <p>ServerSocket有一个队列，存放还没有来得及处理的客户端Socket，这个队列的容量就是backlog的含义。 </p>
     * <p>如果队列已经被客户端socket占满了，如果还有新的连接过来，那么ServerSocket会拒绝新的连接。 </p>
     * <p>也就是说backlog提供了容量限制功能，避免太多的客户端socket占用太多服务器资源。 </p>
     * <p>客户端每次创建一个Socket对象，服务端的队列长度就会增加1个 ---> new Socket("127.0.0.1", 8888); </p>
     *<p>服务端每次accept()，就会从队列中取出一个元素 ---> Socket client = server.accept(); </p>
     */
    public void setBackLog(Integer backLog) {
        this.backLog = backLog;
    }
}
